<!--
 * @Descripttion: 对象选择框
 * @LastEditors: xzh
 * @LastEditTime: 2023-09-15 22:54:24
-->
<template>
  <teleport to="#selectItem-select-container" :disabled="!appendToBody">
    <DileLayer
      v-model="selectItemParam.visible"
      :layerWidth="600"
      :layerHeight="700"
      :title="
        $t('common.selectArr.select') +
        $t(selectTypeLabel[selectType] || 'common.selectArr.object') +
        (!!multiple ? $t('common.multiple') : '')
      "
      @sure="handleSure"
      @close="handleClose"
    >
      <div class="selectItem-container">
        <!-- 工具栏 -->
        <div class="selectItem-tool">
          <el-input
            v-model="selectItemParam.keyWord"
            size="large"
            :placeholder="$t('common.enter')"
            :suffix-icon="Search"
            @input="handleKeyWordChange"
          />
        </div>
        <!-- 选择对象内容 -->
        <div class="selectItem-content">
          <div class="content-tree">
            <div class="content-title">
              <span>{{
                $t(selectTypeLabel[selectType] || "common.selectArr.object")
              }}</span>
            </div>
            <div class="content-main">
              <el-scrollbar v-loading="selectItemParam.treeLoading">
                <!-- 对象树 -->
                <el-tree
                  ref="treeRef"
                  node-key="id"
                  class="dile-tree"
                  :data="selectItemParam.treeData"
                  :default-expanded-keys="selectItemParam.defaultExpandedKeys"
                  :expand-on-click-node="expandOnClickNode"
                  :props="selectItemParam.treeProps"
                  :filter-node-method="handleFilterNode"
                  @node-click="handleNodeCick"
                >
                  <template #default="{ node, data }">
                    <div class="tree-node">
                      <SvgIcon :size="1" :name="getSvgName(data)" />
                      <span>{{ node.label }}</span>
                    </div>
                  </template>
                </el-tree>
              </el-scrollbar>
            </div>
          </div>
          <div class="content-selected">
            <div class="content-title">
              <span>{{
                $t("common.selectArr.hasSelected") +
                (!!multiple ? `(${selectItemParam.selectedArr.length})` : "")
              }}</span>
              <el-button text @click="selectItemParam.selectedArr = []">{{
                $t("common.clear")
              }}</el-button>
            </div>
            <div class="content-main">
              <!-- 对象列表 -->
              <div
                class="item-li"
                v-for="(item, index) in selectItemParam.selectedArr"
                :key="index"
              >
                <span>{{ item.name }}</span>
                <el-button
                  type="danger"
                  :icon="Close"
                  size="small"
                  circle
                  @click="selectItemParam.selectedArr.splice(index, 1)"
                />
              </div>
            </div>
          </div>
        </div>
      </div>
    </DileLayer>
  </teleport>
</template>

<script setup lang="ts">
import { ref, reactive, toRefs, computed } from "vue";
import { Search, Close } from "@element-plus/icons-vue";
import { object_Inf } from "@/utils/typings/index.type";
import { selectTypeEnum, selectTypeLabel } from "../index.type";
import { useI18n } from "vue-i18n";
import SvgIcon from "@/assets/icons/index.vue";
import DileLayer from "@/components/dile-layer/index.vue";
import Dile_APi from "@/api";
import Dile_Methods from "@/utils/methods";
import { ElNotification } from "element-plus";

let { t } = useI18n();

const emit = defineEmits(["close", "sure"]);
const props = defineProps({
  // 已选数据
  selectedData: {
    type: [String, Number],
    requited: false,
    default: "",
  },
  // 已选数据名称
  selectedLabel: {
    type: String,
    requited: false,
    default: "",
  },
  // 选择类型(部门|人员)
  selectType: {
    type: String,
    requited: false,
    default: selectTypeEnum.depart,
  },
  //多选
  multiple: {
    type: Boolean,
    requited: false,
    default: false,
  },
  //是否在点击节点的时候展开或者收缩节点
  expandOnClickNode: {
    type: Boolean,
    requited: false,
    default: true,
  },
  //自身是否插入至 body
  appendToBody: {
    type: Boolean,
    requited: false,
    default: true,
  },
  //额外查询条件
  extraConditions: {
    type: Object,
    requited: false,
    default: {},
  },
  //过滤数据id
  filterIds: {
    type: Array,
    requited: false,
    default: [],
  },
});
/**
 * @Author: xzh
 * @Descripttion: 树节点实例
 * @Param:
 */
let treeRef = ref<any>(null);
/**
 * @Author: xzh
 * @Descripttion: 默认数据
 * @Param:
 */
let defaultData = () => ({
  visible: false,
  //已选数据
  selectedArr: [],
  //树数据源
  treeData: [],
  //默认展开节点
  defaultExpandedKeys: [],
});
/**
 * @Author: xzh
 * @Descripttion: 选择对象参数
 * @Param:
 */
let selectItemParam = reactive<object_Inf>({
  keyWord: "",
  treeLoading: false,
  treeProps: {
    children: "children",
    label: "name",
    value: "id",
  },
  ...defaultData(),
});
/**
 * @Author: xzh
 * @Descripttion: 获取svg名称
 * @Param:
 * @param {*} data
 */
let getSvgName = (data: object_Inf) => {
  let svgName = "";
  switch (props.selectType) {
    case selectTypeEnum.store:
    case selectTypeEnum.region:
    case selectTypeEnum.equipType:
    case selectTypeEnum.equipSpareType:
    case selectTypeEnum.executeRule:
      //仓库、区域、设备类型、备件类型
      svgName = "store";
      break;
    default:
      svgName = data.type == 2 ? "person" : "departFolder";
      break;
  }
  return svgName;
};

/**
 * @Author: xzh
 * @Descripttion: 初始化
 * @Param:
 */
let init = async () => {
  let { visible } = toRefs(selectItemParam);
  //初始化数据
  Object.assign(selectItemParam, defaultData());
  visible.value = true;
  // 加载对象tree;
  initSelectItemTree();
};

/**
 * @Author: xzh
 * @Descripttion: 加载对象tree
 * @Param:
 */
let initSelectItemTree = async () => {
  let { treeLoading, treeData, defaultExpandedKeys, selectedArr } =
    toRefs(selectItemParam);
  try {
    treeLoading.value = true;
    //获取组织类型信息
    let selectItemData: Array<object_Inf> = [];

    switch (props.selectType) {
      case selectTypeEnum.depart:
        //获取部门信息
        selectItemData = await Dile_APi.getDepartmentList({
          keyword: "",
          ...props.extraConditions,
        });
        break;
      case selectTypeEnum.post:
        //获取岗位信息
        selectItemData =
          (await Dile_APi.getPostmentList()) as Array<object_Inf>;
        break;
      case selectTypeEnum.people:
        //人员
        selectItemData = [await Dile_APi.getDepartUserTree()];
        break;
      case selectTypeEnum.team:
        //班组
        selectItemData = (await Dile_APi.getTeamList()) as Array<object_Inf>;
        break;
      case selectTypeEnum.store:
        //获取仓库
        selectItemData = await Dile_APi.getStoreList();
        break;
      case selectTypeEnum.region:
        //获取区域
        selectItemData = await Dile_APi.getRegionList();
        break;
      case selectTypeEnum.position:
        //获取存放位置
        selectItemData = (await Dile_APi.getPositionList()).map(
          (x: object_Inf) => ({ ...x, name: x.position })
        );
        break;
      case selectTypeEnum.executeRule:
        //获取执行规则
        selectItemData =
          (await Dile_APi.getExecuteRuleList()) as Array<object_Inf>;
        break;
      case selectTypeEnum.customerType:
        //客户类型
        selectItemData =
          (await Dile_APi.getCustomerTypeList()) as Array<object_Inf>;
        break;
      case selectTypeEnum.customer:
        //客户类型
        selectItemData =
          (await Dile_APi.getCustomerList()) as Array<object_Inf>;
        break;
      case selectTypeEnum.product:
        //产品
        selectItemData = (await Dile_APi.getProductList()) as Array<object_Inf>;
        break;
      case selectTypeEnum.processDefine:
        //工序定义
        selectItemData =
          (await Dile_APi.getProcessDefineList()) as Array<object_Inf>;
        break;
      case selectTypeEnum.equipType:
        //获取设备类型
        selectItemData = await Dile_APi.getEquipTypeList();
        break;
      case selectTypeEnum.equipSpareType:
        //获取设备备件类型
        selectItemData = await Dile_APi.getEquipSpareTypeList();
        break;
      case selectTypeEnum.equipSpare:
        //获取设备备件
        selectItemData =
          (await Dile_APi.getEquipSpareLedgerPageList()) as Array<object_Inf>;
        break;
      case selectTypeEnum.equipFaultType:
        //获取设备故障类型
        selectItemData = await Dile_APi.getEquipRepairTypeList();
        break;
      case selectTypeEnum.equipUpkeepPlan:
        //设备保养计划
        selectItemData =
          (await Dile_APi.getEquipUpkeepPlanPageList()) as Array<object_Inf>;
        break;
      case selectTypeEnum.mold:
        //模具类型
        selectItemData =
          (await Dile_APi.getMoldArchivesList()) as Array<object_Inf>;
        break;
      case selectTypeEnum.moldType:
        //模具类型
        selectItemData =
          (await Dile_APi.getMoldTypeList()) as Array<object_Inf>;
        break;
      case selectTypeEnum.moldFaultType:
        //模具故障类型
        selectItemData =
          (await Dile_APi.getMoldRepairTypeList()) as Array<object_Inf>;
        break;
      case selectTypeEnum.moldUpkeepPlan:
        //模具保养计划
        selectItemData =
          (await Dile_APi.getMoldUpkeepPlanList()) as Array<object_Inf>;
        break;
      case selectTypeEnum.moldSpare:
        //模具备件
        selectItemData =
          (await Dile_APi.getMoldSpareLedgerList()) as Array<object_Inf>;
        break;
      case selectTypeEnum.moldSpareType:
        //模具备件类型
        selectItemData =
          (await Dile_APi.getMoldSpareTypeList()) as Array<object_Inf>;
        break;
    }
    //格式化树数据源
    let treeDataArr = formTreeData(selectItemData);
    //默认展开第一个节点
    if (treeDataArr.length > 0) {
      defaultExpandedKeys.value = [treeDataArr.find(() => true) || {}].map(
        (x: object_Inf) => x.id
      );
      treeData.value = treeDataArr;
    }
    if (
      !!props.selectedData &&
      !Dile_Methods.isGuidFormat(props.selectedData as string)
    ) {
      //加载已选数据
      let selectedLabelArr = String(props.selectedLabel)?.split(",");
      selectedArr.value = String(props.selectedData)
        ?.split(",")
        ?.filter((x) => !!x)
        .map((value, index) => ({ id: value, name: selectedLabelArr[index] }));
    }
  } finally {
    treeLoading.value = false;
  }
};

/**
 * @Author: xzh
 * @Descripttion: 格式化树数据源
 * @Param:
 * @param {*} selectItemData
 */
let formTreeData = (selectItemData: Array<object_Inf>) => {
  //过滤停用&&删除的对象
  selectItemData = Dile_Methods.filterDataArr(
    //过滤传入过滤主键数据
    selectItemData.filter((x) => !props.filterIds.includes(x.id))
  );
  //格式化成树结构
  if (
    [
      selectTypeEnum.depart,
      selectTypeEnum.store,
      selectTypeEnum.region,
      selectTypeEnum.equipType,
      selectTypeEnum.equipSpareType,
      selectTypeEnum.equipFaultType,
      selectTypeEnum.moldType,
      selectTypeEnum.moldSpareType,
      selectTypeEnum.moldFaultType,
    ].includes(props.selectType as selectTypeEnum)
  ) {
    let { treeData } = Dile_Methods.formatToTree(selectItemData);
    return treeData;
  }
  return selectItemData;
};

/**
 * @Author: xzh
 * @Descripttion: 节点点击事件
 * @Param:
 * @param {*} node
 */
let handleNodeCick = (node: object_Inf) => {
  let { selectedArr } = toRefs(selectItemParam);
  //只能选择子节点||人员类型&&不是人员节点
  if (
    ((node.children || []).length > 0 && !!props.expandOnClickNode) ||
    (props.selectType == selectTypeEnum.people && node.type != 2)
  ) {
    return false;
  }
  !!props.multiple
    ? !selectedArr.value.find((x: object_Inf) => x.id == node.id) &&
      selectedArr.value.push(node)
    : (selectedArr.value = [node]);
};

/**
 * @Author: xzh
 * @Descripttion: 关键字修改
 * @Param:
 */
let handleKeyWordChange = () => {
  treeRef.value?.filter(selectItemParam.keyWord);
};

/**
 * @Author: xzh
 * @Descripttion:
 * @Param:
 */
let handleFilterNode = (value: string, data: object_Inf) => {
  if (!value) {
    return true;
  }
  return data.name.includes(value);
};

/**
 * @Author: xzh
 * @Descripttion: 保存数据
 * @Param:
 */
let handleSure = () => {
  let { selectedArr, visible } = toRefs(selectItemParam);
  if (selectedArr.value.length == 0) {
    ElNotification({
      message: t("common.message.pleaseCheckRow"),
      type: "warning",
    });
    return false;
  }
  emit("sure", selectedArr.value);
  //关闭弹框
  visible.value = false;
};

/**
 * @Author: xzh
 * @Descripttion: 关闭事件
 * @Param:
 */
let handleClose = () => {
  emit("close");
  //关闭弹框
  selectItemParam.visible = false;
};

defineExpose({
  init,
});
</script>
<style lang="scss" scoped>
.selectItem-container {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: var(--selectItem-space);
  gap: var(--selectItem-space);
  .selectItem-tool {
    flex: 3rem 0 0;
  }
  .selectItem-content {
    display: flex;
    flex-direction: row;
    flex: 1;
    height: 0;
    .content-tree {
      .content-title {
        border-right: 0;
      }
      .content-main {
        border-right: 0;
        border-top: 0;
      }
    }
    .content-selected {
      .content-main {
        border-top: 0;
      }
    }
    > div {
      display: flex;
      flex-direction: column;
      flex-basis: 50%;
      > .content-title {
        flex: 2rem 0 0;
        border: 1px solid var(--el-border-color);
        padding: 0 var(--selectItem-space);
        display: flex;
        justify-content: space-between;
        align-items: center;
        overflow: hidden;
        :deep(.el-button) {
          padding: 0;
          span {
            font-weight: 700;
          }
        }
      }
      > .content-main {
        flex: 1;
        border: 1px solid var(--el-border-color);
        display: flex;
        flex-direction: column;
        overflow: auto;
        padding: 0.5rem 0;
        :deep(.tree-node) {
          display: flex;
          flex-direction: row;
          justify-content: flex-start;
          align-items: center;
          gap: 0.5rem;
          span {
            margin-left: 0;
          }
        }
        .item-li {
          display: flex;
          flex-direction: row;
          justify-content: space-between;
          align-items: center;
          padding: 0 var(--selectItem-space);
          .el-button {
            width: 1rem;
            height: 1rem;
          }
          span {
            color: var(--el-text-color-regular);
            font-size: var(--el-font-size-base);
          }
        }
      }
    }
  }
  --selectItem-space: 1rem;
}
</style>
